<?php
/**
 * EGP Framework
 *
 * LICENSE
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author     Akon(番茄红了) <aultoale@gmail.com>
 * @copyright  Copyright (c) 2008 (http://www.tblog.com.cn)
 * @license    http://www.gnu.org/licenses/gpl.html     GPL 3
 */

!defined('EGP_LIB_DIR') && die('Access Deny!');

/**
 * 自定通用函数集
 *
 * <i>以下的函数，很可能在其他的框架中已经被定义过了</i>
 *
 * @package    function
 * @author     Akon(番茄红了) <aultoale@gmail.com>
 * @copyright  Copyright (c) 2008 (http://www.tblog.com.cn)
 * @license    http://www.gnu.org/licenses/gpl.html     GPL 3
 */

if (!function_exists('array_merge_deep')) {
    /**
     * 递归地合并一个或多个数组(不同于 array_merge_recursive )
     *
     * @return array
     */
    function array_merge_deep()
    {
        $a = func_get_args();
        for ($i = 1; $i < count($a); $i++) {
            foreach ($a[$i] as $k => $v) {
                if (isset($a[0][$k])) {
                    if (is_array($v)) {
                        if (is_array($a[0][$k])) {
                            $a[0][$k] = array_merge_deep($a[0][$k], $v);
                        } else {
                            $v[] = $a[0][$k];
                            $a[0][$k] = $v;
                        }
                    } else {
                        $a[0][$k] = is_array($a[0][$k]) ? array_merge($a[0][$k], array($v)) : $v;
                    }
                } else {
                    $a[0][$k] = $v;
                }
            }
        }
        return $a[0];
    }
}

if (!function_exists('stripslashes_deep')) {
    /**
     * 支持数组形态的 stripslashes
     *
     * @param  mixed  $value
     * @return mixed
     */
    function stripslashes_deep($value)
    {
        return is_array($value) ?
                array_map('stripslashes_deep', $value) :
                stripslashes($value);
    }
}

if (!function_exists('addslashes_deep')) {
    /**
     * 支持数组形态的 addslashes
     *
     * @param  mixed  $value
     * @return mixed
     */
    function addslashes_deep($value)
    {
        return is_array($value) ?
                array_map('addslashes_deep', $value) :
                addslashes($value);
    }
}

if (!function_exists('lcfirst')) {
    /**
     * Make a string's first character lowercase
     *
     * @param  string  $string
     * @return string
     */
    function lcfirst($string)
    {
        $string = (string) $string;
        return empty($string) ? '' : strtolower($string{0}) . substr($string, 1);
    }
}

if (!function_exists('lcwords')) {
    /**
     * Lowercase the first character of each word in a string
     *
     * @param  string  $string
     * @return string
     */
    function lcwords($string)
    {
        $tokens = explode(' ', $string);
        if (!is_array($tokens) || count($tokens) <= 1)
            return lcfirst($string);
        $result = array();
        foreach ($tokens as $token)
            $result[] = lcfirst($token);
        return implode(' ', $result);
    }
}

if (!function_exists('str_break')) {
    /**
     * 按指定的长度切割字符串
     *
     * @param  string   $string     需要切割的字符串
     * @param  integer  $length     长度
     * @param  string   $suffix     切割后补充的字符串
     * @return string
     */
    function str_break($string, $length, $suffix = '')
    {
        if (strlen($string) <= $length + strlen($suffix))
            return $string;

        $n = $tn = $noc = 0;
        while ($n < strlen($string)) {
            $t = ord($string[$n]);
            if ($t == 9 || $t == 10 || (32 <= $t && $t <= 126)) {
                $tn = 1; $n++; $noc++;
            } elseif (194 <= $t && $t <= 223) {
                $tn = 2; $n += 2; $noc += 2;
            } elseif (224 <= $t && $t < 239) {
                $tn = 3; $n += 3; $noc += 2;
            } elseif (240 <= $t && $t <= 247) {
                $tn = 4; $n += 4; $noc += 2;
            } elseif (248 <= $t && $t <= 251) {
                $tn = 5; $n += 5; $noc += 2;
            } elseif ($t == 252 || $t == 253) {
                $tn = 6; $n += 6; $noc += 2;
            } else {
                $n++;
            }
            if ($noc >= $length)
                break;
        }
        $noc > $length && $n -= $tn;
        $strcut = substr($string, 0, $n);
        if (strlen($strcut) < strlen($string)) {
            $strcut .= $suffix;
        }
        return $strcut;
    }
}

if (!function_exists('zh_strlen')) {
    /**
     * 获取中文字符长度(包括全角字符)
     *
     * @param  string  $str
     * @return integer
     */
    function zh_strlen($str)
    {
        $len = strlen($str);
        $n = $i = 0;
        while($i < $len){
            if (preg_match('/^[' . chr(0xa1) . '-' . chr(0xff) . ']+$/', $str[$i])) {
                $i += 2;
            } else {
                $i++;
            }
            $n++;
        }
        return $n;
    }
}

if (!function_exists('light_keyword')) {
    /**
     * 字符串高亮
     *
     * @param  string  $string   需要的高亮的字符串
     * @param  string  $keyword  关键字
     * @return string
     */
    function light_keyword($string, $keyword)
    {
        if ($string && $keyword) {
            if (!is_array($keyword)) {
                $keyword = array($keyword);
            }
            $keyword = array_map('trim', $keyword);
            $pattern = array();
            foreach ($keyword as $word) {
                $word && $pattern[] = '(' . preg_quote($word) . ')';
            }
            $pattern && $string = preg_replace(
                '/(' . implode('|', $pattern) . ')/is',
                '<span class="highlight">\\1</span>',
                $string
            );
        }
        return $string;
    }
}

if (!function_exists('html2txt')) {
    /**
     * 将 HTML 转换为文本
     *
     * @param  string  $html
     * @return string
     */
    function html2txt($html)
    {
        $html = trim($html);
        if (empty($html))
            return $html;
        $search = array("'<script[^>]*?>.*?</script>'si",
            "'<style[^>]*?>.*?</style>'si",
            "'<[\/\!]*?[^<>]*?>'si",
            "'([\r\n])[\s]+'",
            "'&(quot|#34);'i",
            "'&(amp|#38);'i",
            "'&(lt|#60);'i",
            "'&(gt|#62);'i",
            "'&(nbsp|#160)[;]*'i",
            "'&(iexcl|#161);'i",
            "'&(cent|#162);'i",
            "'&(pound|#163);'i",
            "'&(copy|#169);'i",
            "'&#(\d+);'e"
        );
        $replace = array("", "", "", "\\1", "\"", "&", "<", ">", " ",
                         chr(161), chr(162), chr(163), chr(169), "chr(\\1)");
        return preg_replace($search, $replace, $html);
    }
}

if (!function_exists('dnl2br')) {
    /**
     * 重写 nl2br
     *
     * @param  string  $text
     * @return string
     */
    function dnl2br($text)
    {
        return str_replace(array("\r\n", "\r", "\n"), "<br />", str_replace('  ', '&nbsp;&nbsp;', $text));
    }
}

if (!function_exists('url2link')) {
    /**
     * 将内容中的 URL 地址转换为超链接
     *
     * @param  string  $text
     * @param  string  $target
     * @return string
     */
    function url2link($text, $target = '_blank')
    {
        $pattern = '/https?:\/\/([a-z0-9\-]+\.)+[a-z]{2,3}([a-z0-9_~#%&\/\'\+\=\:\?\.\-])*/i';
        preg_match_all($pattern, $text, $matches);
        if (isset($matches[0]) && !empty($matches[0])) {
            $matches = array_unique($matches[0]);
            foreach ($matches as $url) {
                $tmp = $url;
                $length = 65;
                if(strlen($tmp) > $length) {
                    $tmp = substr($tmp, 0, intval($length * 0.5)) . ' ... ' . substr($tmp, - intval($length * 0.3));
                }
                $text = str_replace($url, "<a href=\"$url\" target=\"$target\" title=\"$url\">$tmp</a>", $text);
            }
        }
        return $text;
    }
}

if (!function_exists('get_client_ip')) {
    /**
     * 获取客户端IP地址
     *
     * @return string
     */
    function get_client_ip()
    {
        $ip = $proxy = NULL;
        if (!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) {
            if (!empty($_SERVER["HTTP_CLIENT_IP"])) {
                $proxy = $_SERVER["HTTP_CLIENT_IP"];
            } else {
                $proxy = $_SERVER["REMOTE_ADDR"];
            }

            // When a HTTP request is proxied, some proxy server will add requester's
            // IP address to $_SERVER['HTTP_X_FORWARDED_FOR'].
            // As a request may go through several proxies,
            // $_SERVER['HTTP_X_FORWARDED_FOR'] can contain several IP addresses separated with comma.
            $ips = explode(', ', $_SERVER['HTTP_X_FORWARDED_FOR']);

            $n = count($ips);
            for ($i = 0; $i < $n; $i++) {
                $ips[$i] = trim($ips[$i]);
                // Skip RFC 1918 IP's 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16
                if (!preg_match('/^(?:10|172\.(?:1[6-9]|2\d|3[01])|192\.168)\./', $ips[$i])) {
                    if (ip2long($ips[$i]) != false) {
                        $ip = $ips[$i];
                        break;
                    }
                }
            }
            if (empty($ip)) {
                $ip = $proxy;
            }
        } else {
            if (isset($_SERVER["HTTP_CLIENT_IP"])) {
                $ip = $_SERVER["HTTP_CLIENT_IP"];
            } else {
                $ip = $_SERVER["REMOTE_ADDR"];
            }
        }

        return $ip;
    }
}

if (!function_exists('md5_mix')) {
    /**
     * 对任意类型进行 md5 加密
     *
     * @param  mixed  $mixed
     * @return string
     */
    function md5_mix($mixed)
    {
        return md5(var_export($mixed, true));
    }
}

if (!function_exists('url_ping')) {
    /**
     * 判断网址是否可以正常访问
     *
     * @param  string  $url
     * @return boolean
     */
    function url_ping($url)
    {
        $headers = @get_headers($url);
        if (isset($headers[0])) {
            preg_match('/ (\d{3}) /', $headers[0], $matches);
            if (isset($matches[1]) && $matches[1] < 400) {
                return true;
            }
        }
        return false;
    }
}

if (!function_exists('post_to_url')) {
    /**
     * 使用POST的方式发送数据到指定的网址
     *
     * @param  string  $url
     * @return boolean
     */
    function post_to_url($url, array $post)
    {
        $data = http_build_query($post);
        $options = array (
            'http' => array (
                'method'  => 'POST',
                'header'  => "Content-type: application/x-www-form-urlencoded\r\n" . "Content-Length: " . strlen($data) . "\r\n",
                'content' => $data
            )
        );
        $context = stream_context_create($options);
        return file_get_contents($url, false, $context);
    }
}

if (!function_exists('strip_html')) {
    /**
     * strip_tags的修改版
     *
     * @param  string  $str
     * @return string
     */
    function strip_html($str)
    {
        $str = strip_tags(preg_replace('/(\s|&nbsp;|<br ?\/?>)+/i', ' ', $str));
        $str = trim(preg_replace('/[\s\x{3000}]+/u', ' ', $str));
        return $str;
    }
}

if (!function_exists('imagebmp')) {
    /**
     *  以 BMP 格式将图像输出到浏览器或文件
     *
     * @param  resource  $image        图像资源
     * @param  string    $filename     如果要另存为文件，请指定文件名，为空则直接在浏览器输出
     * @return boolean
     */
    function imagebmp(&$im, $filename = null)
    {
        if (!$im) {
            return false;
        }
        $w = imagesx($im);
        $h = imagesy($im);
        $result = '';

        if (!imageistruecolor($im)) {
            $tmp = imagecreatetruecolor($w, $h);
            imagecopy($tmp, $im, 0, 0, 0, 0, $w, $h);
            imagedestroy($im);
            $im = & $tmp;
        }

        $biBPLine = $w * 3;
        $biStride = ($biBPLine + 3) & ~3;
        $biSizeImage = $biStride * $h;
        $bfOffBits = 54;
        $bfSize = $bfOffBits + $biSizeImage;

        $result .= substr('BM', 0, 2);
        $result .= pack('VvvV', $bfSize, 0, 0, $bfOffBits);
        $result .= pack('VVVvvVVVVVV', 40, $w, $h, 1, 24, 0, $biSizeImage, 0, 0, 0, 0);

        $numpad = $biStride - $biBPLine;
        for ($y = $h - 1; $y >= 0; --$y) {
            for ($x = 0; $x < $w; ++$x) {
                $col = imagecolorat ($im, $x, $y);
                $result .=  substr(pack ('V', $col), 0, 3);
            }
            for ($i = 0; $i < $numpad; ++$i) {
                $result .= pack ('C', 0);
            }
        }

        if(null == $filename){
            header("Content-Type: image/bmp");
            echo $result;
        } else {
            $file = fopen($filename, "wb");
            fwrite($file, $result);
            fclose($file);
        }

        return true;
    }

}

if (!function_exists('imagecreatefrombmp')) {
    /**
     * 从 BMP 文件或 URL 新建一图像
     *
     * @param  string  $filename
     * @return resource
     */
    function imagecreatefrombmp($filename)
    {
        if (!($f1 = fopen($filename, "rb"))) {
            return false;
        }

        $file = unpack("vfile_type/Vfile_size/Vreserved/Vbitmap_offset", fread($f1, 14));
        if ($file['file_type'] != 19778) {
            return false;
        }

        $bmp = unpack('Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel'.
                      '/Vcompression/Vsize_bitmap/Vhoriz_resolution'.
                      '/Vvert_resolution/Vcolors_used/Vcolors_important', fread($f1, 40));

        $bmp['colors'] = pow(2, $bmp['bits_per_pixel']);
        if ($bmp['size_bitmap'] == 0) {
            $bmp['size_bitmap'] = $file['file_size'] - $file['bitmap_offset'];
        }
        $bmp['bytes_per_pixel'] = $bmp['bits_per_pixel'] / 8;
        $bmp['bytes_per_pixel2'] = ceil($bmp['bytes_per_pixel']);
        $bmp['decal'] = ($bmp['width']*$bmp['bytes_per_pixel'] / 4);
        $bmp['decal'] -= floor($bmp['width'] * $bmp['bytes_per_pixel'] / 4);
        $bmp['decal'] = 4 - ( 4 * $bmp['decal']);

        if ($bmp['decal'] == 4) {
            $bmp['decal'] = 0;
        }

        $palette = array();
        if ($bmp['colors'] < 16777216) {
            $palette = unpack('V' . $bmp['colors'], fread($f1, $bmp['colors'] * 4));
        }

        $IMG = fread($f1, $bmp['size_bitmap']);
        $vide = chr(0);
        $res = imagecreatetruecolor($bmp['width'], $bmp['height']);
        $P = 0;
        $y = $bmp['height'] - 1;

        while ($y >= 0) {
            $x = 0;
            while ($x < $bmp['width']) {
                if ($bmp['bits_per_pixel'] == 24) {
                    $color = unpack('V', substr($img, $p, 3) . $vide);
                } elseif ($bmp['bits_per_pixel'] == 16) {
                    $color = unpack('n', substr($img, $p, 2));
                    $color[1] = $palette[$color[1] + 1];
                } elseif ($bmp['bits_per_pixel'] == 8) {
                    $color = unpack('n', $vide . substr($img, $P, 1));
                    $color[1] = $palette[$color[1] + 1];
                } elseif ($bmp['bits_per_pixel'] == 4){
                    $color = unpack("n", $vide . substr($img, floor($P), 1));
                    if (($P * 2) % 2 == 0) {
                        $color[1] = ($color[1] >> 4);
                    } else {
                        $color[1] = ($color[1] & 0x0F);
                    }
                    $color[1] = $palette[$color[1] + 1];
                } elseif ($bmp['bits_per_pixel'] == 1) {
                    $color = unpack("n", $vide . substr($img, floor($P), 1));
                        if (($P * 8) % 8 == 0) $color[1] =  $color[1]         >> 7;
                    elseif (($P * 8) % 8 == 1) $color[1] = ($color[1] & 0x40) >> 6;
                    elseif (($P * 8) % 8 == 2) $color[1] = ($color[1] & 0x20) >> 5;
                    elseif (($P * 8) % 8 == 3) $color[1] = ($color[1] & 0x10) >> 4;
                    elseif (($P * 8) % 8 == 4) $color[1] = ($color[1] & 0x8 ) >> 3;
                    elseif (($P * 8) % 8 == 5) $color[1] = ($color[1] & 0x4 ) >> 2;
                    elseif (($P * 8) % 8 == 6) $color[1] = ($color[1] & 0x2 ) >> 1;
                    elseif (($P * 8) % 8 == 7) $color[1] = ($color[1] & 0x1 );
                    $color[1] = $palette[$color[1] + 1];
                } else {
                    return false;
                }
                imagesetpixel($res, $x, $y, $color[1]);
                $X++;
                $p += $bmp['bytes_per_pixel'];
            }
            $y--;
            $p += $bmp['decal'];
        }

        fclose($f1);

        return $res;
    }
}
